package com.gitee.l0km.beanfilter.core;

import java.util.Objects;
import java.util.Set;

import com.google.common.collect.FluentIterable;

/**
 * 字段过滤简单实现
 * @author guyadong
 *
 */
public class SimpleFieldFilter extends BaseFieldFilter {
	private final FlexibleContextFilter flexibleFilter;
	public SimpleFieldFilter(Class<?> beanClass, boolean whiteList,String... filterNames) {
		this(beanClass, 
				false,
				whiteList, 
				whiteList ? EMPTY_STRING_ARRAY : filterNames,
				whiteList ?  filterNames: EMPTY_STRING_ARRAY,
				null,
				null, true, EMPTY_STRING_ARRAY, EMPTY_STRING_ARRAY);
	}
	public SimpleFieldFilter(Class<?> beanClass, boolean autoCase,boolean whiteList,String... filterNames) {
		this(beanClass, 
				autoCase,
				whiteList, 
				whiteList ? EMPTY_STRING_ARRAY : filterNames,
				whiteList ?  filterNames: EMPTY_STRING_ARRAY,
				null,
				null, true, EMPTY_STRING_ARRAY, EMPTY_STRING_ARRAY);
	}
	/**
	 * {@code @com.gitee.l0km.beanfilter.core.annotations.FieldNameFilter} 注解定义的 构造方法
	 * @param beanClass Java Bean类型
	 * @param autoCase 是否将snake-case和camel-case格式的字段字视为同一字段，如firstName和first_name,为{@code true}时视为同一个名字。
	 * @param whiteList 为{@code true}时为白名单模式，{@code filterNames}指定字段名被允许输入/输出，否则为黑名单模式，{@code filterNames}指定字段名被禁止输入/输出
	 * @param filterNames 过滤的字段名列表
	 * @param activeOnClasses 过滤器激活器类型列表，必须为{@link Activation}接口实现
	 * @param activeOnClassNames  过滤器激活器类名列表，必须为{@link Activation}接口实现类名,与{@code activeOnClasses}参数作用相同，用字符器定义类名在特定场景可以减少依赖
	 * @param and 指定多个过滤器激活器时，激活判断模式，为{@code true}为AND模式，所有激活器条件都匹配才能激活过滤器，否则为OR模式，任意一激活器条件都匹配就可以激活过滤器
	 * @param defaultExcludeNames 默认排除字段，黑名单模式有效
	 * @param defaultIncludeNames 默认包含字段，白名单模式有效
	 */
	public SimpleFieldFilter(Class<?> beanClass, boolean autoCase,boolean whiteList,String[] filterNames,
			Class<?>[] activeOnClasses, String[] activeOnClassNames, boolean and, 
			String[] defaultExcludeNames, String[] defaultIncludeNames) {
		this(beanClass, 
				autoCase,
				whiteList, 
				whiteList ? EMPTY_STRING_ARRAY : filterNames,
				whiteList ?  filterNames: EMPTY_STRING_ARRAY,
				activeOnClasses, activeOnClassNames, 
				and, 
				whiteList ? EMPTY_STRING_ARRAY : defaultExcludeNames, 
				whiteList ?  defaultIncludeNames : EMPTY_STRING_ARRAY);
	}
	public SimpleFieldFilter(Class<?> beanClass, boolean autoCase,String[] excludeNames,String[] includeNames) {
		this(beanClass, 
				autoCase, 
				null == excludeNames || excludeNames.length ==0, 
				null == excludeNames ? EMPTY_STRING_ARRAY:excludeNames,
				null == includeNames ? EMPTY_STRING_ARRAY:includeNames,
				null, null, 
				true, 
				EMPTY_STRING_ARRAY, EMPTY_STRING_ARRAY);
	}
	protected SimpleFieldFilter(Class<?> beanClass, boolean autoCase,boolean whiteList,String[] excludeNames,
			String[] includeNames, Class<?>[] activeOnClasses, String[] activeOnClassNames, 
			boolean and, String[] defaultExcludeNames, String[] defaultIncludeNames) {
		super(beanClass, autoCase, whiteList, excludeNames, includeNames, activeOnClasses, activeOnClassNames, and);
		this.flexibleFilter = new FlexibleContextFilter(beanClass, autoCase, whiteList, defaultExcludeNames,
				defaultIncludeNames, EMPTY_CLASS_ARRAY, EMPTY_STRING_ARRAY, true);
	}
	@Override
	public Set<String> getExcludeNames() {
		Set<String> _excludeNames = super.getExcludeNames();
		if(!isWhiteList() && !flexibleFilter.excludeMetas.isEmpty()) {
			_excludeNames = FluentIterable.from(_excludeNames).append(flexibleFilter.getExcludeNames()).toSet();
		}
		return _excludeNames;
	}
	@Override
	public Set<String> getIncludeNames() {
		Set<String> _includeNames = super.getIncludeNames();
		if(isWhiteList() && !flexibleFilter.includeMetas.isEmpty()) {
			_includeNames = FluentIterable.from(_includeNames).append(flexibleFilter.getIncludeNames()).toSet();
		}
		return _includeNames;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = super.hashCode();
		result = prime * result + Objects.hash(flexibleFilter);
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (!super.equals(obj))
			return false;
		if (getClass() != obj.getClass())
			return false;
		SimpleFieldFilter other = (SimpleFieldFilter) obj;
		return Objects.equals(flexibleFilter, other.flexibleFilter);
	}
	@Override
	public String toString() {
		StringBuilder builder = new StringBuilder();
		builder.append("SimpleFieldFilter [dyamicFieldFilter=").append(flexibleFilter).append(", toString()=")
				.append(super.toString()).append("]");
		return builder.toString();
	}
}
